﻿#region Copyright RenGuiYou. All rights reserved.
//=====================================================
// NeatlyFrameWork
// Author:      RenGuiyou
// Feedback: 	mailto:750539605@qq.com
//=====================================================
#endregion
using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class NJoystick : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler
{
    private Action m_OnMoveStart;
    private Action<int, int> m_OnMove;
    private Action m_OnMoveEnd;
    [SerializeField] private Graphic m_BackGround;
    [SerializeField] private Graphic m_Thumb;
    [SerializeField] private bool m_IsDynamic;
    [SerializeField] private float m_Radius = 50;
    [SerializeField] private float m_InitPositionY = -300;
    private float m_IntervalTime = 0;
    private float m_DeltaTime = 0;
    private bool m_InMove = false;
    private const int FORMAT_MULTI = 10000;
    private RectTransform m_RectTransform;
    private Vector2 m_CurrentPosition = Vector2.zero;
    private Vector2 m_StartPosition = Vector2.zero;
    private Vector2 m_LastPosition = Vector2.zero;

    void Awake()
    {
        m_RectTransform = transform as RectTransform;
        if (m_IsDynamic)
        {
            HideThumb();
        }
        m_InMove = false;
    }

    public void Register(Action onMoveStart, Action<int, int> onMove, Action onMoveEnd, float time = 0)
    {
        m_OnMoveStart = onMoveStart;
        m_OnMove = onMove;
        m_OnMoveEnd = onMoveEnd;
        m_IntervalTime = time;
    }

    public void AddMoveStartListener(Action onMoveStart)
    {
        m_OnMoveStart = onMoveStart;
    }

    public void AddMoveListener(Action<int, int> onMove)
    {
        m_OnMove = onMove;
    }

    public void AddMoveEndListener(Action onMoveEnd)
    {
        m_OnMoveEnd = onMoveEnd;
    }

    private void HideThumb()
    {
        m_BackGround.SetAnchoredPosition(0, m_InitPositionY);
        m_Thumb.SetAnchoredPosition(0, m_InitPositionY);
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        ResetLocalPoint(eventData);
        if (m_IsDynamic)
        {
            m_BackGround.rectTransform.anchoredPosition = m_CurrentPosition;
            m_Thumb.rectTransform.anchoredPosition = m_CurrentPosition;
            m_StartPosition = m_CurrentPosition;
        }
        m_OnMoveStart?.Invoke();
        m_InMove = true;
        m_DeltaTime = 0;
        m_LastPosition = Vector2.zero;
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        if (m_IsDynamic)
        {
            HideThumb();
        }
        else
        {
            m_Thumb.rectTransform.anchoredPosition = Vector2.zero;
        }
        m_OnMoveEnd?.Invoke();
        m_InMove = false;
        m_LastPosition = Vector2.zero;
    }

    public void OnDrag(PointerEventData eventData)
    {
        ResetLocalPoint(eventData);
        m_LastPosition = (m_CurrentPosition - m_StartPosition).normalized;
        if (Vector2.Distance(m_CurrentPosition, m_StartPosition) > m_Radius)
        {
            m_Thumb.rectTransform.anchoredPosition = m_LastPosition * m_Radius + m_StartPosition;
        }
        else
        {
            m_Thumb.rectTransform.anchoredPosition = m_CurrentPosition;
        }
    }

    public void OnUpdate()
    {
        if (m_InMove)
        {
            if (m_DeltaTime <= 0)
            {
                if (m_OnMove != null)
                {
                    m_OnMove((int)(m_LastPosition.x * FORMAT_MULTI), (int)(m_LastPosition.y * FORMAT_MULTI));
                }
                m_DeltaTime = m_IntervalTime;
            }
            m_DeltaTime -= Time.deltaTime;
        }
    }

    public int GetFormatPositionX()
    {
        return (int)(m_LastPosition.x * FORMAT_MULTI);
    }

    public int GetFormatPositionY()
    {
        return (int)(m_LastPosition.y * FORMAT_MULTI);
    }

    private void ResetLocalPoint(PointerEventData eventData)
    {
        RectTransformUtility.ScreenPointToLocalPointInRectangle(m_RectTransform, eventData.position, eventData.pressEventCamera, out m_CurrentPosition);
    }
}